import { Injectable, Logger } from '@nestjs/common';
import { DatabaseService } from './database.service';
import { TransactionType } from '@prisma/client';
import { Connection, PublicKey } from '@solana/web3.js';

@Injectable()
export class TransactionService {
  private readonly logger = new Logger(TransactionService.name);
  private connection: Connection;

  constructor(private prisma: DatabaseService) {
    this.connection = new Connection(
      process.env.SOLANA_RPC_URL || 'https://api.devnet.solana.com',
      'confirmed'
    );
  }

  /**
   * 记录交易到数据库
   */
  async recordTransaction(data: {
    signature: string;
    from: string;
    to: string;
    amount: number;
    type: TransactionType;
    tokenMint?: string;
    metadata?: any;
  }) {
    try {
      // 首先验证交易是否已确认
      const txInfo = await this.connection.getSignatureStatus(data.signature);
      
      if (!txInfo.value || txInfo.value.err) {
        this.logger.warn(`Transaction ${data.signature} not confirmed or failed`);
        return null;
      }

      // 获取交易详细信息
      const txDetails = await this.connection.getTransaction(data.signature, {
        commitment: 'confirmed',
        maxSupportedTransactionVersion: 0
      });

      if (!txDetails) {
        this.logger.warn(`Transaction details not found for ${data.signature}`);
        return null;
      }

      const transaction = await this.prisma.transaction.create({
        data: {
          signature: data.signature,
          from: data.from,
          to: data.to,
          amount: data.amount,
          type: data.type,
          tokenMint: data.tokenMint,
          blockTime: txDetails.blockTime ? new Date(txDetails.blockTime * 1000) : new Date(),
          slot: BigInt(txDetails.slot),
          fee: txDetails.meta?.fee ? txDetails.meta.fee / 1_000_000_000 : 0, // 转换为 SOL
          status: 'confirmed',
          metadata: data.metadata,
        },
      });

      this.logger.log(`Transaction recorded: ${data.signature}`);
      
      // 返回前将 BigInt 转换为字符串，避免序列化错误
      return {
        ...transaction,
        slot: transaction.slot.toString(),
      };
    } catch (error) {
      this.logger.error(`Failed to record transaction ${data.signature}:`, error);
      throw error;
    }
  }

  /**
   * 批量检查并记录交易
   */
  async verifyAndRecordTransaction(
    signature: string,
    transactionData: {
      from: string;
      to: string;
      amount: number;
      type: TransactionType;
      tokenMint?: string;
      metadata?: any;
    }
  ) {
    try {
      // 检查交易是否已存在
      const existingTx = await this.prisma.transaction.findUnique({
        where: { signature }
      });

      if (existingTx) {
        this.logger.log(`Transaction ${signature} already recorded`);
        return {
          ...existingTx,
          slot: existingTx.slot.toString(),
        };
      }

      // 记录新交易
      return await this.recordTransaction({
        signature,
        ...transactionData
      });
    } catch (error) {
      this.logger.error(`Failed to verify and record transaction:`, error);
      return null;
    }
  }

  /**
   * 获取代币的交易历史
   */
  async getTokenTransactions(tokenMint: string, limit: number = 50) {
    const transactions = await this.prisma.transaction.findMany({
      where: { tokenMint },
      orderBy: { blockTime: 'desc' },
      take: limit,
      include: { token: true }
    });

    // 将 BigInt 转换为字符串
    return transactions.map(tx => ({
      ...tx,
      slot: tx.slot.toString(),
    }));
  }

  /**
   * 获取用户的交易历史
   */
  async getUserTransactions(userPublicKey: string, limit: number = 50) {
    const transactions = await this.prisma.transaction.findMany({
      where: {
        OR: [
          { from: userPublicKey },
          { to: userPublicKey }
        ]
      },
      orderBy: { blockTime: 'desc' },
      take: limit,
      include: { token: true }
    });

    // 将 BigInt 转换为字符串
    return transactions.map(tx => ({
      ...tx,
      slot: tx.slot.toString(),
    }));
  }
}
